#include <bits/stdc++.h>
using namespace std;
int T;
int n,m,l,v;
struct node
{
    int d,v,a;
    int st,ed;
    bool out;
    int cnt;
    //cnt means how much detection can know it is detecting
    //st means the start of detecting
    //ed means the end of detecting
    // out means whether it is detecting
}car[100005];
int road[100005];
int cnt[100005];
bool cmp(int a,int b)
{
    return a < b;
}
bool vis[100005];
bool ans = false;
void check(int mid,int step)
{
    if(step == mid)
    {
        bool flag = true;
        for(int i = 1; i <= n; i++)
        {
            bool lflag = false;
            for(int j = 1; j <= m; j++)
            {

                if(vis[j] == 1)
                {
                    if(car[i].out == true)
                    {
                        if(car[i].st <= road[j] && car[i].ed >= road[j])
                        {
                            lflag = true;
                            break;
                        }
                    }
                }
            }
            flag &= lflag;
        }
        if(flag)
        {
            ans = true;
            return ;
        }
        else
        {
            return ;
        }
    }
    for(int i = 1; i <= m; i++)
    {
        if(vis[i] == 0)
        {
            vis[i] = 1;
            check(mid,step+1);
            vis[i] = 0;
        }
    }
}

int main()
{
    freopen("detect.in","r",stdin);
    freopen("detect.out","w",stdout);
    cin >> T;
    while(T--)
    {
        memset(road,0,sizeof(road));
        memset(vis,0,sizeof(vis));
        cin >> n >> m >> l >> v;
        for(int i = 1; i <= n; i++)
        {
            cin >> car[i].d >> car[i].v >> car[i].a;
            if(car[i].a == 0)
            {
               if(car[i].v > v)
               {
                   car[i].st = car[i].d;
                   car[i].ed = l;
               }
               else
               {
                   car[i].st = car[i].ed = l+1;
               }
            }
            else if(car[i].a > 0)
            {
                car[i].st = car[i].d + max(0,((v*v-car[i].v*car[i].v)/(2*car[i].a))+1);
                car[i].ed = l;
            }
            else if(car[i].a < 0)
            {
                if(car[i].v <= v)
                {
                    car[i].st = car[i].ed = l+1;
                }
                else
                {
                    car[i].st = car[i].d;
                    car[i].ed = max(car[i].d + ((v*v-car[i].v*car[i].v)/(2*car[i].a)),car[i].st);
                }
            }
            //cout << car[i].st << " " << car[i].ed << endl;
        }
        for(int i = 1; i <= m; i++)
        {
            cin >> road[i];
        }
        road[m+1] = 1e9;
        road[0] = 0;
        sort(road,road+m+2,cmp);
        int ans1 = 0;

        for(int i = 1; i <= n; i++)
        {
            int tmp = upper_bound(road+1,road+m+1,car[i].ed)-road;
            if(car[i].st < road[tmp-1])
            {
                car[i].out = true;
                ans1++;
                int tmp2 = lower_bound(road+1,road+m+1,car[i].st)-road;
                car[i].cnt = tmp-tmp2-1;
            }
        }
        cout << ans1 << " ";
        int l = 0,r = m;
        int mid;
        int o = 0;
        while(l <= r)
        {
            mid = l+(r-l)/2;
            for(int i = 1; i <= m;i++)
            {
                vis[i] = 1;
                check(mid,1);
                vis[i] = 0;
            }
            if(ans == true)
            {
                ans = false;
                o = mid;
                r = mid-1;
            }
            else
            {
                l = mid+1;
            }

        }
        cout << m-o << endl;
    }
    return 0;
}
